﻿/*
 * Copyright (c) 2011 Shawn Rakowski
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to 
 * deal in the Software without restriction, including without limitation the 
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
 * sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 * SOFTWARE. 
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ROS.Persistence;
using ROS.Application.DomainObjects;
using ROS.Application.DTO;

namespace ROS.Application
{
    internal class OrderService
    {
        #region Fields

        OrderDataMapper orderDataMapper;
        MenuItemDataMapper menuItemDataMapper;

        #endregion

        #region Properties
        #endregion

        #region Constructor

        public OrderService()
        {
            orderDataMapper = new OrderDataMapper();
            menuItemDataMapper = new MenuItemDataMapper();
        }

        #endregion

        #region Methods

        /// <summary>
        /// This routine creates a new order in the system.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="tableNumber"></param>
        /// <param name="guestCount"></param>
        /// <param name="notes"></param>
        /// <returns></returns>
        internal ROSStatus NewOrder(long userID, int tableNumber, int guestCount, string notes, out long orderNumber)
        {
            // default the output of the routine
            orderNumber = default(long);

            // ensure the user exists in the system
            UserDataMapper userDM = new UserDataMapper();
            User user = userDM.FindByID(userID);
            if (user == null)
                return ROSStatus.ERROR_INVALID_USER;

            // create the order
            Order order = new Order(tableNumber, guestCount, notes);

            // assign the user who entered the order to the order
            order.EnteredBy = user;

            // save the order in storage
            orderDataMapper.Create(order);

            // set the output to the order id.
            orderNumber = order.ID;

            // report that the routine ran to successful completion
            return ROSStatus.SUCCESS;
        }

        internal IList<DTO.OrderDTO> GetActiveOrders()
        {
            IList<Order> activeOrders = orderDataMapper.FindAll();
            List<OrderDTO> activeOrderDTOs = new List<OrderDTO>();
            foreach (Order order in activeOrders)
            {
                activeOrderDTOs.Add(loadOrderDTOFromOrder(order));
            }
            return activeOrderDTOs;
        }

        internal DTO.OrderDTO GetOrderByID(long orderID)
        {
            Order order = orderDataMapper.FindByID(orderID);
            return loadOrderDTOFromOrder(order);
        }

        /// <summary>
        /// This routine adds a quantity of some menu item to an order. 
        /// </summary>
        /// <param name="orderID"></param>
        /// <param name="menuItemID"></param>
        /// <param name="quantity"></param>
        /// <returns></returns>
        internal ROSStatus AddMenuItemToOrder(long orderID, long menuItemID, int quantity)
        {
            //Ensure a quantity of the menu item is actually be added to the order
            if (quantity <= 0)
            {
                //return a status indicating the quantity is invalid
                return ROSStatus.INVALID_QUANTITY;
            }    

            //Ensure the order id is valid in form before we try and look it up.
            //The order id must be a positive value
            if (orderID <= 0)
            {
                //if it isnt then return a status indicating the order is invalid
                return ROSStatus.INVALID_ORDER;
            }

            //Get the order from storage
            Order order = orderDataMapper.FindByID(orderID);
            //if order is not found
            if (order == null)
            {
                //return a status indicating the order is invalid
                return ROSStatus.INVALID_ORDER;
            }

            //Ensure the menu item id is valid in form before we try to look it up
            //The menu item id must be a postive value
            if (menuItemID <= 0)
            {
                //if it isn't return a status indicating it is invalid
                return ROSStatus.INVALID_MENU_ITEM;
            }

            //Get the menu item from storage
            MenuItem menuItem = menuItemDataMapper.FindByID(menuItemID);
            //if menu item is not found
            if (menuItem == null)
            {
                //return a status indicating menu item is invalid
                return ROSStatus.INVALID_MENU_ITEM;
            }

            //Create a new order item
            OrderItem orderItem = new OrderItem();

            //assign the menu item to the order item
            orderItem.MenuItem = menuItem;

            //copy the menu item price to the unit price of the order item
            orderItem.UnitPrice = menuItem.Price;

            //copy the quantity to the order item
            orderItem.Quantity = quantity;

            //add the order item to the order
            order.AddOrderItem(orderItem);

            //Save the order
            orderDataMapper.Update(order);

            //return a status indicating the addition was successful
            return ROSStatus.SUCCESS;
        }

        private DTO.OrderDTO loadOrderDTOFromOrder(Order order)
        {
            OrderDTO orderDTO = new OrderDTO();
            orderDTO.ID = order.ID;
            orderDTO.TableNumber = order.TableNumber;
            orderDTO.GuestCount = order.GuestCount;
            orderDTO.Notes = order.Notes;
            orderDTO.Price = order.CalculateOrderPrice(Currency.USD).ToString();
            return orderDTO;
        }

        #endregion
    }
}
